package org.xbill.DNS;

import java.io.IOException;
import java.io.PrintStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

public class Cache
{
  private static final int defaultMaxEntries = 50000;
  private CacheMap data;
  private int dclass;
  private int maxcache;
  private int maxncache;

  public Cache()
  {
    this(1);
  }

  public Cache(int paramInt)
  {
    this.maxncache = -1;
    this.maxcache = -1;
    this.dclass = paramInt;
    this.data = new CacheMap(50000);
  }

  public Cache(String paramString)
    throws IOException
  {
    this.maxncache = -1;
    this.maxcache = -1;
    this.data = new CacheMap(50000);
    Master localMaster = new Master(paramString);
    while (true)
    {
      Record localRecord = localMaster.nextRecord();
      if (localRecord == null)
        return;
      addRecord(localRecord, 0, localMaster);
    }
  }

  /**
   * @deprecated
   */
  private void addElement(Name paramName, Element paramElement)
  {
    monitorenter;
    try
    {
    }
    finally
    {
      while (true)
      {
        int j;
        while (true)
        {
          Element localElement;
          while (true)
          {
            Object localObject2;
            int i;
            while (true)
            {
              List localList;
              monitorexit;
              throw localObject1;
              if (((Element)localList.get(j)).getType() != i)
                break label191;
              localList.set(j, paramElement);
            }
            localElement = (Element)localObject2;
            if (localElement.getType() != i)
              break;
            this.data.put(paramName, paramElement);
          }
          LinkedList localLinkedList = new LinkedList();
          localLinkedList.add(localElement);
          localLinkedList.add(paramElement);
          this.data.put(paramName, localLinkedList);
        }
        label191: ++j;
      }
    }
  }

  /**
   * @deprecated
   */
  private Element[] allElements(Object paramObject)
  {
    Element localElement;
    Element[] arrayOfElement;
    monitorenter;
    try
    {
      if (paramObject instanceof List)
      {
        List localList = (List)paramObject;
        arrayOfElement = (Element[])localList.toArray(new Element[localList.size()]);
        monitorexit;
        return arrayOfElement;
      }
      localElement = (Element)paramObject;
      arrayOfElement = new Element[1];
    }
    finally
    {
      monitorexit;
    }
  }

  /**
   * @deprecated
   */
  private Object exactName(Name paramName)
  {
    monitorenter;
    try
    {
      Object localObject2 = this.data.get(paramName);
      monitorexit;
      return localObject2;
    }
    finally
    {
      localObject1 = finally;
      monitorexit;
      throw localObject1;
    }
  }

  /**
   * @deprecated
   */
  private Element findElement(Name paramName, int paramInt1, int paramInt2)
  {
    Element localElement;
    Object localObject3;
    monitorenter;
    try
    {
      Object localObject2 = exactName(paramName);
      if (localObject2 == null)
      {
        localObject3 = null;
        monitorexit;
        return localObject3;
      }
      localElement = oneElement(paramName, localObject2, paramInt1, paramInt2);
    }
    finally
    {
      monitorexit;
    }
  }

  private RRset[] findRecords(Name paramName, int paramInt1, int paramInt2)
  {
    RRset[] arrayOfRRset;
    SetResponse localSetResponse = lookupRecords(paramName, paramInt1, paramInt2);
    if (localSetResponse.isSuccessful())
      arrayOfRRset = localSetResponse.answers();
    while (true)
    {
      return arrayOfRRset;
      arrayOfRRset = null;
    }
  }

  private final int getCred(int paramInt, boolean paramBoolean)
  {
    int i;
    if (paramInt == 1)
      if (paramBoolean)
        i = 4;
    while (true)
    {
      while (true)
      {
        while (true)
        {
          while (true)
          {
            return i;
            i = 3;
          }
          if (paramInt != 2)
            break label37;
          if (!(paramBoolean))
            break;
          i = 4;
        }
        i = 3;
      }
      label37: if (paramInt != 3)
        break;
      i = 1;
    }
    throw new IllegalArgumentException("getCred: invalid section");
  }

  private static int limitExpire(long paramLong1, long paramLong2)
  {
    int i;
    if ((paramLong2 >= 0L) && (paramLong2 < paramLong1))
      paramLong1 = paramLong2;
    long l = paramLong1 + System.currentTimeMillis() / 1000L;
    if ((l < 0L) || (l > 2147483647L))
      i = 2147483647;
    while (true)
    {
      return i;
      i = (int)l;
    }
  }

  private static void markAdditional(RRset paramRRset, Set paramSet)
  {
    if (paramRRset.first().getAdditionalName() == null)
      return;
    Iterator localIterator = paramRRset.rrs();
    while (true)
    {
      Name localName;
      do
      {
        if (!(localIterator.hasNext()));
        localName = ((Record)localIterator.next()).getAdditionalName();
      }
      while (localName == null);
      paramSet.add(localName);
    }
  }

  /**
   * @deprecated
   */
  private Element oneElement(Name paramName, Object paramObject, int paramInt1, int paramInt2)
  {
    monitorenter;
    Object localObject1 = null;
    if (paramInt1 == 255);
    try
    {
      throw new IllegalArgumentException("oneElement(ANY)");
    }
    finally
    {
      List localList;
      int j;
      monitorexit;
      throw localObject3;
      if (paramObject instanceof List)
      {
        localList = (List)paramObject;
        j = 0;
      }
      while (true)
      {
        Object localObject2;
        int k = localList.size();
        if (j >= k)
        {
          if (localObject1 != null)
            break label130;
          localObject2 = null;
        }
        while (true)
        {
          while (true)
          {
            while (true)
            {
              while (true)
              {
                Element localElement1;
                do
                {
                  while (true)
                  {
                    monitorexit;
                    return localObject2;
                    Element localElement2 = (Element)localList.get(j);
                    if (localElement2.getType() != paramInt1)
                      break label181;
                    localObject1 = localElement2;
                  }
                  localElement1 = (Element)paramObject;
                }
                while (localElement1.getType() != paramInt1);
                localObject1 = localElement1;
              }
              label130: if (!(localObject1.expired()))
                break;
              removeElement(paramName, paramInt1);
              localObject2 = null;
            }
            int i = localObject1.compareCredibility(paramInt2);
            if (i >= 0)
              break;
            localObject2 = null;
          }
          localObject2 = localObject1;
        }
        label181: ++j;
      }
    }
  }

  /**
   * @deprecated
   */
  private void removeElement(Name paramName, int paramInt)
  {
    Object localObject2;
    monitorenter;
    try
    {
      localObject2 = this.data.get(paramName);
      if (localObject2 == null)
      {
        monitorexit;
        return;
      }
      if (localObject2 instanceof List);
    }
    finally
    {
      while (true)
      {
        do
          while (true)
          {
            List localList;
            int i;
            monitorexit;
            throw localObject1;
            ++i;
          }
        while (((Element)localObject2).getType() != paramInt);
        this.data.remove(paramName);
      }
    }
  }

  /**
   * @deprecated
   */
  private void removeName(Name paramName)
  {
    monitorenter;
    try
    {
      this.data.remove(paramName);
      monitorexit;
      return;
    }
    finally
    {
      localObject = finally;
      monitorexit;
      throw localObject;
    }
  }

  public SetResponse addMessage(Message paramMessage)
  {
    Name localName1;
    int k;
    int l;
    Object localObject;
    HashSet localHashSet;
    RRset[] arrayOfRRset1;
    int i1;
    int i3;
    Name localName2;
    int i4;
    RRset[] arrayOfRRset2;
    RRset localRRset1;
    RRset localRRset2;
    int i5;
    RRset[] arrayOfRRset3;
    int i8;
    SetResponse localSetResponse2;
    int i12;
    int i14;
    boolean bool1 = paramMessage.getHeader().getFlag(5);
    Record localRecord = paramMessage.getQuestion();
    int i = paramMessage.getHeader().getRcode();
    int j = 0;
    SetResponse localSetResponse1 = null;
    boolean bool2 = Options.check("verbosecache");
    if (((i != 0) && (i != 3)) || (localRecord == null))
      localSetResponse2 = null;
    while (true)
    {
      return localSetResponse2;
      localName1 = localRecord.getName();
      k = localRecord.getType();
      l = localRecord.getDClass();
      localObject = localName1;
      localHashSet = new HashSet();
      arrayOfRRset1 = paramMessage.getSectionRRsets(1);
      i1 = 0;
      int i2 = arrayOfRRset1.length;
      if (i1 < i2)
        break;
      label110: arrayOfRRset2 = paramMessage.getSectionRRsets(2);
      localRRset1 = null;
      localRRset2 = null;
      i5 = 0;
      int i6 = arrayOfRRset2.length;
      if (i5 < i6)
        break label581;
      if (j != 0)
        break label725;
      if (i != 3)
        break label669;
      i12 = 0;
      if ((i != 3) && (localRRset1 == null) && (localRRset2 != null))
        break label682;
      int i13 = getCred(2, bool1);
      SOARecord localSOARecord = null;
      if (localRRset1 != null)
        localSOARecord = (SOARecord)localRRset1.first();
      addNegative((Name)localObject, i12, localSOARecord, i13);
      if (localSetResponse1 == null)
      {
        if (i != 3)
          break label676;
        i14 = 1;
        localSetResponse1 = SetResponse.ofType(i14);
      }
      arrayOfRRset3 = paramMessage.getSectionRRsets(3);
      i8 = 0;
      int i9 = arrayOfRRset3.length;
      if (i8 < i9)
        break label761;
      if (bool2)
        System.out.println("addMessage: " + localSetResponse1);
      localSetResponse2 = localSetResponse1;
    }
    if (arrayOfRRset1[i1].getDClass() != l);
    do
      while (true)
      {
        while (true)
        {
          while (true)
            ++i1;
          i3 = arrayOfRRset1[i1].getType();
          localName2 = arrayOfRRset1[i1].getName();
          i4 = getCred(1, bool1);
          if (((i3 != k) && (k != 255)) || (!(localName2.equals(localObject))))
            break;
          addRRset(arrayOfRRset1[i1], i4);
          j = 1;
          if (localObject == localName1)
          {
            if (localSetResponse1 == null)
              localSetResponse1 = new SetResponse(6);
            RRset localRRset5 = arrayOfRRset1[i1];
            localSetResponse1.addRRset(localRRset5);
          }
          markAdditional(arrayOfRRset1[i1], localHashSet);
        }
        if ((i3 != 5) || (!(localName2.equals(localObject))))
          break;
        addRRset(arrayOfRRset1[i1], i4);
        if (localObject == localName1)
        {
          RRset localRRset4 = arrayOfRRset1[i1];
          localSetResponse1 = new SetResponse(4, localRRset4);
        }
        localObject = ((CNAMERecord)arrayOfRRset1[i1].first()).getTarget();
      }
    while ((i3 != 39) || (!(((Name)localObject).subdomain(localName2))));
    addRRset(arrayOfRRset1[i1], i4);
    if (localObject == localName1)
    {
      RRset localRRset3 = arrayOfRRset1[i1];
      localSetResponse1 = new SetResponse(5, localRRset3);
    }
    DNAMERecord localDNAMERecord = (DNAMERecord)arrayOfRRset1[i1].first();
    try
    {
      Name localName5 = ((Name)localObject).fromDNAME(localDNAMERecord);
      label669: label676: label682: label581: label725: label761: localObject = localName5;
    }
    catch (NameTooLongException localNameTooLongException)
    {
      while (true)
      {
        do
          while (true)
          {
            do
            {
              while (true)
              {
                while (true)
                {
                  break label110:
                  if (arrayOfRRset2[i5].getType() == 6)
                  {
                    Name localName4 = arrayOfRRset2[i5].getName();
                    if (((Name)localObject).subdomain(localName4))
                      localRRset1 = arrayOfRRset2[i5];
                  }
                  while (true)
                  {
                    Name localName3;
                    do
                    {
                      do
                        while (true)
                          ++i5;
                      while (arrayOfRRset2[i5].getType() != 2);
                      localName3 = arrayOfRRset2[i5].getName();
                    }
                    while (!(((Name)localObject).subdomain(localName3)));
                    localRRset2 = arrayOfRRset2[i5];
                  }
                  i12 = k;
                }
                i14 = 2;
              }
              int i15 = getCred(2, bool1);
              addRRset(localRRset2, i15);
              markAdditional(localRRset2, localHashSet);
            }
            while (localSetResponse1 != null);
            localSetResponse1 = new SetResponse(3, localRRset2);
          }
        while ((i != 0) || (localRRset2 == null));
        int i7 = getCred(2, bool1);
        addRRset(localRRset2, i7);
        markAdditional(localRRset2, localHashSet);
      }
      int i10 = arrayOfRRset3[i8].getType();
      if ((i10 != 1) && (i10 != 28) && (i10 != 38));
      while (true)
      {
        do
          while (true)
            ++i8;
        while (!(localHashSet.contains(arrayOfRRset3[i8].getName())));
        int i11 = getCred(3, bool1);
        addRRset(arrayOfRRset3[i8], i11);
      }
    }
  }

  /**
   * @deprecated
   */
  public void addNegative(Name paramName, int paramInt1, SOARecord paramSOARecord, int paramInt2)
  {
    monitorenter;
    long l = 0L;
    if (paramSOARecord != null);
    try
    {
      l = paramSOARecord.getTTL();
      Element localElement = findElement(paramName, paramInt1, 0);
      if (l == 0L)
        if ((localElement != null) && (localElement.compareCredibility(paramInt2) <= 0))
          removeElement(paramName, paramInt1);
      do
      {
        monitorexit;
        return;
        if ((localElement != null) && (localElement.compareCredibility(paramInt2) <= 0))
          localElement = null;
      }
      while (localElement != null);
    }
    finally
    {
      monitorexit;
    }
  }

  /**
   * @deprecated
   */
  public void addRRset(RRset paramRRset, int paramInt)
  {
    Name localName;
    Element localElement;
    monitorenter;
    try
    {
      long l = paramRRset.getTTL();
      localName = paramRRset.getName();
      int i = paramRRset.getType();
      localElement = findElement(localName, i, 0);
      if (l == 0L)
      {
        if ((localElement != null) && (localElement.compareCredibility(paramInt) <= 0))
          removeElement(localName, i);
        monitorexit;
        return;
      }
      if ((localElement != null) && (localElement.compareCredibility(paramInt) <= 0))
        localElement = null;
    }
    finally
    {
      while (true)
      {
        monitorexit;
        throw localObject;
        CacheRRset localCacheRRset = new CacheRRset(paramRRset, paramInt, this.maxcache);
      }
    }
  }

  /**
   * @deprecated
   */
  public void addRecord(Record paramRecord, int paramInt, Object paramObject)
  {
    Name localName;
    int i;
    boolean bool;
    monitorenter;
    try
    {
      localName = paramRecord.getName();
      i = paramRecord.getRRsetType();
      bool = Type.isRR(i);
    }
    finally
    {
      while (true)
      {
        Element localElement;
        do
        {
          monitorexit;
          throw localObject;
        }
        while ((localElement.compareCredibility(paramInt) != 0) || (!(localElement instanceof CacheRRset)));
        ((CacheRRset)localElement).addRR(paramRecord);
      }
    }
  }

  /**
   * @deprecated
   */
  public void clearCache()
  {
    monitorenter;
    try
    {
      this.data.clear();
      monitorexit;
      return;
    }
    finally
    {
      localObject = finally;
      monitorexit;
      throw localObject;
    }
  }

  public RRset[] findAnyRecords(Name paramName, int paramInt)
  {
    return findRecords(paramName, paramInt, 2);
  }

  public RRset[] findRecords(Name paramName, int paramInt)
  {
    return findRecords(paramName, paramInt, 3);
  }

  public void flushName(Name paramName)
  {
    removeName(paramName);
  }

  public void flushSet(Name paramName, int paramInt)
  {
    removeElement(paramName, paramInt);
  }

  public int getDClass()
  {
    return this.dclass;
  }

  public int getMaxCache()
  {
    return this.maxcache;
  }

  public int getMaxEntries()
  {
    return this.data.getMaxSize();
  }

  public int getMaxNCache()
  {
    return this.maxncache;
  }

  public int getSize()
  {
    return this.data.size();
  }

  /**
   * @deprecated
   */
  protected SetResponse lookup(Name paramName, int paramInt1, int paramInt2)
  {
    int j;
    int k;
    int l;
    Name localName;
    Object localObject2;
    Object localObject3;
    SetResponse localSetResponse4;
    Element[] arrayOfElement;
    int i2;
    int i3;
    monitorenter;
    try
    {
      int i = paramName.labels();
      j = i;
      if (j < 1)
      {
        SetResponse localSetResponse5 = SetResponse.ofType(0);
        localObject3 = localSetResponse5;
        monitorexit;
        return localObject3;
      }
      if (j == 1)
      {
        k = 1;
        if (j != i)
          break label508;
        l = 1;
        if (k == 0)
          break label514;
        localName = Name.root;
        while (true)
        {
          localObject2 = this.data.get(localName);
          if (localObject2 != null)
            break;
          break label496:
          int i1 = i - j;
          localName = new Name(paramName, i1);
        }
        if ((l != 0) && (paramInt1 == 255))
        {
          localSetResponse4 = new SetResponse(6);
          arrayOfElement = allElements(localObject2);
          i2 = 0;
          i3 = 0;
          int i4 = arrayOfElement.length;
          label514: label496: label508: if (i3 >= i4);
        }
      }
    }
    finally
    {
      while (true)
      {
        while (true)
        {
          do
            while (true)
            {
              while (true)
              {
                while (true)
                {
                  while (true)
                  {
                    while (true)
                    {
                      while (true)
                      {
                        Element localElement3;
                        SetResponse localSetResponse2;
                        Element localElement4;
                        CacheRRset localCacheRRset3;
                        SetResponse localSetResponse3;
                        Element localElement5;
                        int i5;
                        monitorexit;
                        throw localObject1;
                        Element localElement1 = oneElement(localName, localObject2, 39, paramInt2);
                        if ((localElement1 == null) || (!(localElement1 instanceof CacheRRset)))
                          break;
                        CacheRRset localCacheRRset2 = (CacheRRset)localElement1;
                        localObject3 = new SetResponse(5, localCacheRRset2);
                      }
                      Element localElement2 = oneElement(localName, localObject2, 2, paramInt2);
                      if ((localElement2 == null) || (!(localElement2 instanceof CacheRRset)))
                        break;
                      CacheRRset localCacheRRset1 = (CacheRRset)localElement2;
                      localObject3 = new SetResponse(3, localCacheRRset1);
                    }
                    if ((l == 0) || (oneElement(localName, localObject2, 0, paramInt2) == null))
                      break;
                    SetResponse localSetResponse1 = SetResponse.ofType(1);
                    localObject3 = localSetResponse1;
                  }
                  --j;
                }
                k = 0;
              }
              l = 0;
            }
          while (l == 0);
          localName = paramName;
        }
        ++i3;
      }
    }
  }

  public SetResponse lookupRecords(Name paramName, int paramInt1, int paramInt2)
  {
    return lookup(paramName, paramInt1, paramInt2);
  }

  public void setMaxCache(int paramInt)
  {
    this.maxcache = paramInt;
  }

  public void setMaxEntries(int paramInt)
  {
    this.data.setMaxSize(paramInt);
  }

  public void setMaxNCache(int paramInt)
  {
    this.maxncache = paramInt;
  }

  public String toString()
  {
    int i;
    StringBuffer localStringBuffer = new StringBuffer();
    monitorenter;
    try
    {
      Element[] arrayOfElement;
      Iterator localIterator = this.data.values().iterator();
      do
      {
        if (!(localIterator.hasNext()))
        {
          monitorexit;
          return localStringBuffer.toString();
        }
        arrayOfElement = allElements(localIterator.next());
        i = 0;
      }
      while (i >= arrayOfElement.length);
      localStringBuffer.append(arrayOfElement[i]);
      localStringBuffer.append("\n");
    }
    finally
    {
      monitorexit;
    }
  }

  private static class CacheMap extends LinkedHashMap
  {
    private int maxsize = -1;

    CacheMap(int paramInt)
    {
      super(16, 0.75F, true);
      this.maxsize = paramInt;
    }

    int getMaxSize()
    {
      return this.maxsize;
    }

    protected boolean removeEldestEntry(Map.Entry paramEntry)
    {
      int i;
      if ((this.maxsize >= 0) && (size() > this.maxsize))
        i = 1;
      while (true)
      {
        return i;
        i = 0;
      }
    }

    void setMaxSize(int paramInt)
    {
      this.maxsize = paramInt;
    }
  }

  private static class CacheRRset extends RRset
  implements Cache.Element
  {
    private static final long serialVersionUID = 1434009056L;
    int credibility;
    int expire;

    public CacheRRset(RRset paramRRset, int paramInt, long paramLong)
    {
      super(paramRRset);
      this.credibility = paramInt;
      this.expire = Cache.access$0(paramRRset.getTTL(), paramLong);
    }

    public CacheRRset(Record paramRecord, int paramInt, long paramLong)
    {
      this.credibility = paramInt;
      this.expire = Cache.access$0(paramRecord.getTTL(), paramLong);
      addRR(paramRecord);
    }

    public final int compareCredibility(int paramInt)
    {
      return (this.credibility - paramInt);
    }

    public final boolean expired()
    {
      int i;
      if ((int)(System.currentTimeMillis() / 1000L) >= this.expire)
        i = 1;
      while (true)
      {
        return i;
        i = 0;
      }
    }

    public String toString()
    {
      StringBuffer localStringBuffer = new StringBuffer();
      localStringBuffer.append(super.toString());
      localStringBuffer.append(" cl = ");
      localStringBuffer.append(this.credibility);
      return localStringBuffer.toString();
    }
  }

  private static abstract interface Element
  {
    public abstract int compareCredibility(int paramInt);

    public abstract boolean expired();

    public abstract int getType();
  }

  private static class NegativeElement
  implements Cache.Element
  {
    int credibility;
    int expire;
    Name name;
    int type;

    public NegativeElement(Name paramName, int paramInt1, SOARecord paramSOARecord, int paramInt2, long paramLong)
    {
      this.name = paramName;
      this.type = paramInt1;
      long l = 0L;
      if (paramSOARecord != null)
        l = paramSOARecord.getMinimum();
      this.credibility = paramInt2;
      this.expire = Cache.access$0(l, paramLong);
    }

    public final int compareCredibility(int paramInt)
    {
      return (this.credibility - paramInt);
    }

    public final boolean expired()
    {
      int i;
      if ((int)(System.currentTimeMillis() / 1000L) >= this.expire)
        i = 1;
      while (true)
      {
        return i;
        i = 0;
      }
    }

    public int getType()
    {
      return this.type;
    }

    public String toString()
    {
      StringBuffer localStringBuffer = new StringBuffer();
      if (this.type == 0)
        localStringBuffer.append("NXDOMAIN " + this.name);
      while (true)
      {
        localStringBuffer.append(" cl = ");
        localStringBuffer.append(this.credibility);
        return localStringBuffer.toString();
        localStringBuffer.append("NXRRSET " + this.name + " " + Type.string(this.type));
      }
    }
  }
}